# BabyOS如何使用WIFI模组 当MCU项目要增加网络通讯功能时可选择支持串口通讯的WIFI模组。 ![MCU-WIFI硬件框架](../_static/MCU-WIFIHW.png) WIFI模组硬件连接比较简单,仅需一路串口便可以使用。 软件方面使用AT指令或私有协议进行配置和收发数据。 --- BabyOS目标是助力MCU项目的开发,那如何友好的兼容各类模组呢? 以下方案作抛砖引玉之用。 软件方面考虑的点: ① AT指令发送后需要等待回复,裸机如何做到不阻塞的等待 ② 多个AT指令实现一个功能配置,如何将功能与AT指令对应 ③ 各家的指令有差异,但给上层业务调用的接口要做到统一 ④ 模组收到数据后如何抛给上层使用 ## thirdparty增加pt.h 为了让裸机实现不阻塞的等待,BabyOS thirdparty部分增加PT。为了更方便使用,对宏进行了修改: ```C #define PT_WAIT_UNTIL_FOREVER(pt, condition) #define PT_WAIT_UNTIL(pt, condition, timeout) #define PT_WAIT_WHILE(pt, cond) #define PT_DELAY_MS(pt, ms) ``` AT指令的处理便非常方便 ```C static int _bEspMainTask(struct pt *pt) { static uint8_t index = 0; uint16_t retval = 0; PT_BEGIN(pt); while (1) { if (bEspRunInfo[index].pcmd == NULL) { break; } if (*(bEspRunInfo[index].pcmd) == NULL) { ...... break; } //发送AT指令 retval = (*(bEspRunInfo[index].pcmd))(index, &bEspRunInfo[index].param); if (retval > 0) { //带有超时时间的等待,等模组的回复 PT_WAIT_UNTIL(pt, bEspRunInfo[index].at_ack.ack == AT_CMD_ACK_DONE, retval); ...... } ...... //非阻塞延时500ms PT_DELAY_MS(pt, 500); } PT_END(pt); } ``` ## 增加b_mod_wifi软件模块 增加b_mod_wifi,提供统一的接口给上层调用。 调用`bWifiUp`时指定设备号并注册事件处理函数。 `b_mod_wifi`产生事件并通过上层注册的处理函数抛出。 ![BabyOS WIFI模组框架](../_static/WIFISWFRAM.png) b_mod_wifi主要使用`bCtl`接口操作设备。因此接入的模组,其驱动需要实现`b_driver_cmd.h`里所列的命令: ```c /////////////////////////////////////////////////////////// // Wifi Module Command & Data Structure /////////////////////////////////////////////////////////// #define bCMD_WIFI_MODE_STA 0 // none #define bCMD_WIFI_MODE_AP 1 // bApInfo_t #define bCMD_WIFI_MODE_STA_AP 2 // bApInfo_t #define bCMD_WIFI_JOIN_AP 3 // bApInfo_t #define bCMD_WIFI_MQTT_CONN 4 // bMqttConnInfo_t #define bCMD_WIFI_MQTT_SUB 5 // bMqttTopic_t #define bCMD_WIFI_MQTT_PUB 6 // bMqttData_t #define bCMD_WIFI_LOCAL_TCP_SERVER 7 // bTcpUdpInfo_t #define bCMD_WIFI_LOCAL_UDP_SERVER 8 // bTcpUdpInfo_t #define bCMD_WIFI_REMOT_TCP_SERVER 9 // bTcpUdpInfo_t #define bCMD_WIFI_REMOT_UDP_SERVER 10 // bTcpUdpInfo_t #define bCMD_WIFI_PING 11 // default www.baidu.com #define bCMD_WIFI_GET_CONN_STATUS 12 // bWfifiConnStat_t #define bCMD_WIFI_REG_CALLBACK 13 // bWifiModuleCallback_t #define bCMD_WIFI_TCPUDP_CLOSE 14 // bTcpUdpInfo_t #define bCMD_WIFI_TCPUDP_SEND 15 // bTcpUdpData_t ``` ## 增加b_util_queue 上层调用接口,无法立即返回结果。创建队列,给上层调用的接口实质是往队列里抛数据。b_mod_wifi有循环调用的处理函数。从队列中取数据并处理。 ```c static int _bModWifiTask(struct pt *pt) { static bWifiQItem_t item; void *param = NULL; int wait = 0; PT_BEGIN(pt); while (1) { if (bQueuePop(&bModWifiQueue, &item) < 0) { return -1; } ...... if (wait == 1) { PT_WAIT_UNTIL_FOREVER(pt, item.handle->result >= 0); } if (item.release) { item.release(item.param); } memset(&item, 0, sizeof(bWifiQItem_t)); } PT_END(pt); } ``` ## 优化b_util_memp 启用b_mod_wifi时会自动启用动态内存的使用。虽然BabyOS尽量不使用动态内存,但这种场景下没有想到更好的方法,所以决定这一部分使用动态内存。先前只实现了简单的内存池分配,将其重写。 调用bMalloc采用First fit的规则划分空间使用。 调用bFree释放空间,并将相邻的空闲块合并成。 ```C void *bMalloc(uint32_t size); void bFree(void *paddr); uint32_t bGetFreeSize(void); //获取空闲大小 void bMallocFailedHook(void); //bMalloc失败后的处理,弱函数,用户自行实现 ``` ## 公众号助力DIY 使用BabyOS可以很方便的开发一个带网络功能的小玩意。要想通过手机控制设备还需要服务器和APP。BabyOS都已经提供,方便开发者DIY。 MQTT服务: babyos.cn:1883 关注公众号,每个用户都有唯一的topic,给微信公众号发消息便会自动向主题发布消息。 ![mqtt](../_static/mqtt.png) --- 以上内容作为抛砖引玉,期待开发者接入更多的模组。如有问题、建议或者需求,提在仓库的Issue页面。会依次处理。 目前BabyOS的文档不再以pdf形式提供,最新文档的访问入口:https://babyos.cn/doc/